﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FifteenPuzzle
{
    class FifteenPuzzle
    {
        private int[,] puzzle = new int[4, 4];
        private int moves = 0;
        private int x, y;

        private void Swap(ref int x, ref int y){
            int temp = x;
            x = y;
            y = temp;
        }

        private bool CheckWin()
        {
            int k = 1;
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (puzzle[i, j] != k % 16)
                    {
                        return false;
                    }
                    k++;
                }
            }
            return true;
        }
        public FifteenPuzzle()
        {
            #region Create Solvable Board
            int[] numbers = new int[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};
            bool puzzleIsSolvable = false;

            while (!puzzleIsSolvable)
            {
                //randomize the puzzle
                Random r = new Random();
                for (int i = 0; i < 16; i++)
                {
                    Swap(ref numbers[i], ref numbers[r.Next() % 16]);
                }

                //check if solvable
                int sum = 0;
                for (int i = 0; i < 16; i++)
                {
                    if (numbers[i] > 0)
                    {
                        for (int j = i + 1; j < 16; j++)
                        {
                            if (numbers[j] < numbers[i])
                            {
                                sum += numbers[j];
                            }
                        }
                    }
                    else    //if starting position
                    {
                        switch (i)
                        {
                            case 0:
                                sum += 6;
                                break;
                            case 1:
                                sum += 5;
                                break;
                            case 2:
                                sum += 4;
                                break;
                            case 3:
                                sum += 3;
                                break;
                            case 4:
                                sum += 5;
                                break;
                            case 5:
                                sum += 4;
                                break;
                            case 6:
                                sum += 3;
                                break;
                            case 7:
                                sum += 2;
                                break;
                            case 8:
                                sum += 4;
                                break;
                            case 9:
                                sum += 3;
                                break;
                            case 10:
                                sum += 2;
                                break;
                            case 11:
                                sum++;
                                break;
                            case 12:
                                sum += 3;
                                break;
                            case 13:
                                sum += 2;
                                break;
                            case 14:
                                sum++;
                                break;
                            default:
                                break;
                        }
                    }
                }

                if (sum % 2 == 1)
                {
                    puzzleIsSolvable = true;
                }
            }

            int k = 0;
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    puzzle[i, j] = numbers[k];
                    if (numbers[k] == 0)
                    {
                        x = j;
                        y = i;
                    }
                    k++;
                }
            }
            #endregion
        }

        public void Draw()
        {
            Console.Clear();
            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("-----------------");
                Console.WriteLine("|{0, 3}|{1, 3}|{2, 3}|{3, 3}|", puzzle[i, 0], puzzle[i, 1], puzzle[i, 2], puzzle[i, 3]);
            }
            Console.WriteLine("-----------------");
            Console.SetCursorPosition(1, 11);
            Console.WriteLine("Moves : " + moves);
            
        }
        public void Play()
        {
            while (!CheckWin())
            {
                Draw();
                ConsoleKeyInfo keyPress = Console.ReadKey();
                switch (keyPress.Key)
                {
                    case ConsoleKey.UpArrow:
                        if (y > 0)
                        {
                            Swap(ref puzzle[y,x], ref puzzle[y - 1, x]);
                            y--;
                            moves++;
                        }
                        break;
                    case ConsoleKey.DownArrow:
                        if (y < 3)
                        {
                            Swap(ref puzzle[y, x], ref puzzle[y + 1, x]);
                            y++;
                            moves++;
                        }
                        break;
                    case ConsoleKey.LeftArrow:
                        if (x > 0)
                        {
                            Swap(ref puzzle[y, x], ref puzzle[y, x - 1]);
                            x--;
                            moves++;
                        }
                        break;
                    case ConsoleKey.RightArrow:
                        if (x < 3)
                        {
                            Swap(ref puzzle[y, x], ref puzzle[y, x + 1]);
                            x++;
                            moves++;
                        }
                        break;
                    default:
                        break;
                }
            }
            System.Threading.Thread.Sleep(400);
            Console.Clear();
            Console.WriteLine("Winner! You solved the puzzle in " + moves + " moves.");
        }
    }
}
